package phoenix.web.test_objects;

import org.testng.TestException;

import phoenix.core.PhoenixManager;
import phoenix.core.base.extensions.TestBaseWebExt;
import phoenix.core.config.extensions.ConfigExt;
import phoenix.core.data_models.TestUserDataModel;
import phoenix.core.helpers.extensions.WebDriverHelperExt;
import phoenix.web.test_objects.data_model.NotificationsAlerts;
import phoenix.web.test_objects.data_providers.ActivityDataProviders;

/**
 * Class contains test methods for Index page
 */
public class ActivityTests extends TestBaseWebExt
{

	public ActivityTests(PhoenixManager p_phoenix)
	{
		super(p_phoenix);
	}

	public ActivityDataProviders dataProviders = new ActivityDataProviders(manager);
	private final MessengerTests messengerTests = new MessengerTests(manager);

	private final int timeSyncDelay = 60;

	public void activityFavoritsTest(TestUserDataModel p_recepient)
	{
		if (p_recepient == null)
		{
			throw new TestException("p_recepient is null");
		}

		TestUserDataModel origin_user = manager.testUser();

		try
		{
			this.favoritsTest(p_recepient);
		}
		catch (Exception p_ex)
		{
			log().error("activityPagesTest " + p_ex.toString());
		}
		finally
		{
			test().sessionRestore(origin_user);
		}

		test().forErrors();
	}

	public void activityBrowsedTest(TestUserDataModel p_recepient)
	{
		if (p_recepient == null)
		{
			throw new TestException("p_recepient is null");
		}

		TestUserDataModel origin_user = manager.testUser();

		try
		{
			this.browsedMeTest(p_recepient, testUser());
		}
		catch (Exception p_ex)
		{
			log().error("activityPagesTest " + p_ex.toString());
		}
		finally
		{
			test().sessionRestore(origin_user);
		}

		test().forErrors();
	}

	public void activityWinkedTest(TestUserDataModel p_recepient)
	{
		if (p_recepient == null)
		{
			throw new TestException("p_recepient is null");
		}

		TestUserDataModel origin_user = manager.testUser();

		try
		{
			this.winkedMeTest(p_recepient, testUser());
		}
		catch (Exception p_ex)
		{
			log().error("activityPagesTest " + p_ex.toString());
		}
		finally
		{
			test().sessionRestore(origin_user);
		}

		test().forErrors();
	}

	public void notificationBrowseTest(TestUserDataModel p_user)
	{

		// Disable match notifications conflicted with action alerts
		try
		{
			this.prepareForActions(testUser());
			this.prepareForActions(p_user);
		}
		catch (Exception p_ex)
		{
			log().warn(p_ex.toString());
		}

		WebDriverHelperExt.driverHandles = wd().initSecondBrowser();
		try
		{
			// Browse check
			this.doNotificationAlert(manager.testUser(), p_user, "browse");
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen("notificationsTest " + p_ex.toString());
		}
		finally
		{
			wd().getSecondWindow();
			wd().close();
			wd().getPrimaryWindow();
			test().forErrors();
		}
	}

	public void notificationWinkTest(TestUserDataModel p_user)
	{

		// Disable match notifications conflicted with action alerts
		try
		{
			this.prepareForActions(testUser());
			this.prepareForActions(p_user);
		}
		catch (Exception p_ex)
		{
			log().warn(p_ex.toString());
		}

		WebDriverHelperExt.driverHandles = wd().initSecondBrowser();
		try
		{
			// Wink action
			this.doNotificationAlert(manager.testUser(), p_user, "wink");
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen("notificationsTest " + p_ex.toString());
		}
		finally
		{
			wd().getSecondWindow();
			wd().close();
			wd().getPrimaryWindow();
			test().forErrors();
		}
	}

	public void notificationMessageTest(TestUserDataModel p_user)
	{
		// Disable match notifications conflicted with action alerts
		try
		{
			this.prepareForActions(testUser());
			this.prepareForActions(p_user);
		}
		catch (Exception p_ex)
		{
			log().warn(p_ex.toString());
		}

		WebDriverHelperExt.driverHandles = wd().initSecondBrowser();
		try
		{
			// Message action
			this.doNotificationAlert(manager.testUser(), p_user, "message");
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen("notificationsTest " + p_ex.toString());
		}
		finally
		{
			wd().getSecondWindow();
			wd().close();
			wd().getPrimaryWindow();
			test().forErrors();
		}
	}

	public void counterBrowseIncrementTest(TestUserDataModel p_user)
	{
		// Disable match notifications conflicted with action alerts
		try
		{
			this.prepareForActions(p_user);
		}
		catch (Exception p_ex)
		{
			log().warn(p_ex.toString());
		}

		WebDriverHelperExt.driverHandles = wd().initSecondBrowser();

		try
		{
			this.countersIncrementTest(manager.testUser(), p_user, "browse");
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen(p_ex.toString());
		}
		finally
		{
			wd().getSecondWindow();
			wd().close();
			wd().getPrimaryWindow();
			test().forErrors();
		}
	}

	public void counterBrowseDecrementTest(TestUserDataModel p_user)
	{
		try
		{
			this.countersDecrementTest(p_user, "browse");
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen(p_ex.toString());
		}
		finally
		{
			test().forErrors();
		}
	}

	public void counterWinkIncrementTest(TestUserDataModel p_user)
	{
		// Disable match notifications conflicted with action alerts
		try
		{
			this.prepareForActions(p_user);
		}
		catch (Exception p_ex)
		{
			log().warn(p_ex.toString());
		}

		WebDriverHelperExt.driverHandles = wd().initSecondBrowser();

		try
		{
			this.countersIncrementTest(manager.testUser(), p_user, "wink");
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen(p_ex.toString());
		}
		finally
		{
			wd().getSecondWindow();
			wd().close();
			wd().getPrimaryWindow();
			test().forErrors();
		}
	}

	public void counterWinkDecrementTest(TestUserDataModel p_user)
	{
		try
		{
			this.countersDecrementTest(p_user, "wink");
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen(p_ex.toString());
		}
		finally
		{
			test().forErrors();
		}
	}

	public void counterMessageIncrementTest(TestUserDataModel p_user)
	{
		try
		{
			// Disable match notifications conflicted with action alerts
			this.prepareForActions(p_user);
		}
		catch (Exception p_ex)
		{
			log().warn(p_ex.toString());
		}

		WebDriverHelperExt.driverHandles = wd().initSecondBrowser();

		try
		{
			this.countersIncrementTest(manager.testUser(), p_user, "message");
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen(p_ex.toString());
		}
		finally
		{
			wd().getSecondWindow();
			wd().close();
			wd().getPrimaryWindow();
			test().forErrors();
		}
	}

	public void counterMessageDecrementTest(TestUserDataModel p_user)
	{
		try
		{
			this.countersDecrementTest(p_user, "message");
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen(p_ex.toString());
		}
		finally
		{
			test().forErrors();
		}
	}

	private void countersIncrementTest(TestUserDataModel p_userSender, TestUserDataModel p_userRecipient, String p_testType)
	{
		try
		{
			/**
			 * Increment
			 */
			wd().getSecondWindow();
			wd().openAutologin(p_userRecipient);

			Integer counterBeforeActions = page().activityPage().getCounterValue(p_testType);

			// Do actions
			wd().getPrimaryWindow();
			wd().openAutologin(p_userSender);

			switch (p_testType)
			{
				// Do View
				case "browse":
					if (!wd().isUrlContains("/user/view/id/" + p_userRecipient.getId(), false))
					{
						wd().openUserProfile(p_userRecipient);
						wd().refreshPage();
						wd().isUrlContains("/user/view/id/" + p_userRecipient.getId(), true);
						page().userPage().waitForPageLoad();
					}

					break;
				// Do Wink
				case "wink":
					if (!wd().isUrlContains("/user/view/id/" + p_userRecipient.getId(), false))
					{
						wd().openUserProfile(p_userRecipient);
						wd().isUrlContains("/user/view/id/" + p_userRecipient.getId(), true);
						page().userPage().waitForPageLoad();
					}

					page().userPage().clickWink();
					break;
				// Do Message
				case "message":

					messengerTests.sendMessage(p_userSender, p_userRecipient, "Hello");

					if (!page().messenger().isMessagePresent("Hello"))
					{
						throw new TestException("Cannot send message to " + p_userRecipient.getId() + " message is not found in messenger");
					}
					page().messenger().clickClose();
					break;
			}

			// Check counters after actions
			wd().getSecondWindow();
			Integer counterAfterActions = page().activityPage().getCounterValue(p_testType);

			// Test begins
			test().assertGreater(counterBeforeActions, counterAfterActions,
				"Type increment " + p_testType + " from: " + p_userSender.getId() + " to " + p_userRecipient.getId(), true);
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen(
				"countersIncrementTest " + p_testType + " " + p_ex.toString() + " from " + p_userSender.getId() + " to " + p_userRecipient.getId());
		}
		finally
		{
			wd().getPrimaryWindow();
		}
	}

	private void countersDecrementTest(TestUserDataModel p_user, String p_CounterType)
	{
		try
		{

			// Check counters after actions
			wd().openAutologin(p_user);
			Integer counterAfterActions = page().activityPage().getCounterValue(p_CounterType);

			// Click the button at the Toolbar
			this.actionsForDecrementing(testUser(), p_CounterType);

			// Get counters value after made actions
			Integer counterAfterActionsDecrement = page().activityPage().getCounterValue(p_CounterType);

			// Verify test result
			test().assertLower(counterAfterActions, counterAfterActionsDecrement,
				"Type decrement " + p_CounterType + " from: " + p_user.getId() + " to " + p_user.getId(), true);

		}
		catch (Exception p_ex)
		{
			log().errorAndScreen(
				"countersDecrementTest " + p_CounterType + " " + p_ex.toString() + " from " + testUser().getId() + " to " + p_user.getId());
		}
	}

	/**
	 * Do action Browse and checks at Browse page
	 */
	private void browsedMeTest(TestUserDataModel p_userSender, TestUserDataModel p_userRecipient)
	{
		try
		{
			// Do Action
			wd().openAutologin(p_userSender);
			wd().openUserProfile(p_userRecipient);
			wd().wait(2);
			wd().refreshPage();

			wd().wait(timeSyncDelay);

			// Do check
			wd().openAutologin(p_userRecipient);
			wd().openPage("/views");

			if (!page().searchPage().isUserPresent(p_userSender))
			{
				throw new TestException("Unable to find user " + p_userSender.getId());
			}

		}
		catch (Exception p_ex)
		{
			log().errorAndScreen("browsedMeTest " + p_ex.toString());
		}
	}

	/**
	 * Do action Wink and checks at Wink page
	 */
	private void winkedMeTest(TestUserDataModel p_userSender, TestUserDataModel p_userRecipient)
	{
		try
		{
			// Do action
			wd().openAutologin(p_userSender);
			wd().openUserProfile(p_userRecipient);
			manager.web().userPage().clickWink();
			wd().wait(2);
			if (!page().userPage().isWinkedTextPresent())
			{
				throw new TestException("Unable to do wink");
			}

			wd().wait(timeSyncDelay);

			// Do check
			wd().openAutologin(p_userRecipient);
			wd().openPage("/winks");

			if (!page().searchPage().isUserPresent(p_userSender))
			{
				throw new TestException("Unable to find user " + p_userSender.getId());
			}

		}
		catch (Exception p_ex)
		{
			log().errorAndScreen("winkedAtMeTest " + p_ex.toString());
		}
	}

	/**
	 * Add user to friends
	 */
	public void favoritsTest(TestUserDataModel p_user)
	{
		try
		{
			// Do action
			wd().openUserProfile(p_user);
			wd().wait(5);
			page().userPage().clickAddFriends();
			wd().wait(5);
			if (!page().userPage().isFriendsTextPresent())
			{
				throw new TestException("Unable add to friends");
			}

			wd().wait(timeSyncDelay);

			// Do check
			wd().openPage("/favorites");
			if (!page().searchPage().isUserPresent(p_user))
			{
				throw new TestException("Unable to find user " + p_user.getId());
			}
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen("favoritsTest " + p_ex.toString());
		}
	}

	/**
	 * @param p_userSender
	 * @param p_userRecipient
	 * @param p_testType
	 */
	public void doNotificationAlert(TestUserDataModel p_userSender, TestUserDataModel p_userRecipient, String p_testType)
	{
		// Login by recipient
		wd().getSecondWindow();
		wd().openURL(p_userRecipient.getAutologin());

		// Do action by sender
		wd().getPrimaryWindow();
		wd().openURL(p_userSender.getAutologin());

		switch (p_testType)
		{
			case "browse":
				wd().openUserProfile(p_userRecipient);
				wd().refreshPage();
				break;
			case "wink":
				wd().openUserProfile(p_userRecipient);
				if (page().userPage().isWinkedTextPresent())
				{
					throw new TestException("Wink is already made");
				}
				// Do wink
				page().userPage().clickWink();
				break;
			case "message":
				messengerTests.sendMessage(testUser(), p_userRecipient, "Hello");

				if (!page().messenger().isMessagePresent("Hello"))
				{
					throw new TestException("Cannot send message to " + p_userRecipient.getId() + " message is not found in messenger");
				}
				page().messenger().clickClose();
				break;
		}

		wd().getSecondWindow();
		page().activityPage().waitForAlert(p_testType, " from " + p_userSender.getId() + " to " + p_userRecipient.getId());
	}

	/**
	 * Used for prepearing user for counters, notifications tests
	 * @param p_user
	 */
	private void prepareForActions(TestUserDataModel p_user)
	{
		try
		{
			// Enable alerts for Wink, Browse, Message
			wd().openAutologin(p_user);
			NotificationsAlerts params = new NotificationsAlerts();
			params.disableMatchAlerts(); // Disable match alerts
			manager.web().myAccountPage().setMatchNotifications(params);
			params.enableSiteAlerts(); // Enable site action alerts
			manager.backend().notificationsSettingsPage().setNotifications(p_user, params);

			// Unmark as HOT
			backend().searchPage().unsetUserAsHot(p_user);
			backend().searchPage().unsetUserAsScammer(p_user);
			backend().searchPage().verifyPayStatus(p_user);

			wd().wait(5); // Giving some time for data sync
		}
		catch (Exception p_ex)
		{
			log().errorAndScreen(p_ex.toString());
		}
	}

	/**
	 * @param p_userModel
	 * @param p_typeOfAction
	 * @return
	 */
	private void actionsForDecrementing(TestUserDataModel p_userModel, String p_typeOfAction)
	{
		if (p_typeOfAction == "browse")
		{
			wd().openPage("/views");
			page().searchPage().waitForPageLoad();
		}
		else if (p_typeOfAction == "wink")
		{
			wd().openPage("/winks");
			page().searchPage().waitForPageLoad();
		}
		else if (p_typeOfAction == "message")
		{
			wd().openUserProfile(testUser());
			page().messenger().clickMessenger();
			page().messenger().clickClose();
		}
	}
}
